﻿namespace Oddo.Concept.Crm.Common.Security
{
    using System;
    using System.ComponentModel;
    using System.Security;
    using System.Security.Principal;
    using Oddo.Concept.Crm.Common.Extensions;
    using Oddo.Concept.Crm.Common.Interfaces;
    using Oddo.Concept.Crm.Common.Resources;

    /// <summary>
    /// Classe implementant le service d'authentification d'un utilisateur
    /// </summary>
    public class AuthenticationService : IAuthenticationService, INotifyPropertyChangedEx
    {
        private bool _shouldNotifyPropertyChanged = true;
        private bool _authenticating;
        private IPrincipal _currentIdentity;
        private string[] _roles = new string[]{ Labels.role_none };
        private SecureString _password;

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        public bool ShouldNotifyPropertyChanged
        {
            get { return _shouldNotifyPropertyChanged; }
            set { _shouldNotifyPropertyChanged = value; }
        }

        public void NotifyPropertyChanged(string propertyname)
        {
            var handler = PropertyChanged;
            if(handler !=null)
                handler(this, new PropertyChangedEventArgs(propertyname));
        }

        /// <summary>
        /// Determines si l'utilisateur courant est authentifié
        /// </summary>
        public bool IsAuthenticated
        {
            get { return _currentIdentity != null && _currentIdentity.Identity.IsAuthenticated; }
        }

        /// <summary>
        /// Determines si l'authentification est en cours
        /// </summary>
        public bool IsAuthenticating
        {
            get { return _authenticating; }
            private set
            {
                _authenticating = value;
                this.RaisePropertyChanged(() => IsAuthenticating);
            }
        }

        /// <summary>
        /// Obtient l'identité de l'utilisateur
        /// </summary>
        public IPrincipal CurrentIdentity
        {
            get
            {
                return _currentIdentity;
            }
            private set
            {
                _currentIdentity = value; 
                this.RaisePropertyChanged(() => CurrentIdentity);
            }
        }


        /// <summary>
        /// Obtient le nom de l'utilisateur courant
        /// </summary>
        public string UserName
        {
            get { return IsAuthenticated ? CurrentIdentity.Identity.Name : null; }
        }

        /// <summary>
        /// Obtient une liste des roles de l'utilisateur séparés par une virgule
        /// </summary>
        public string UserRoles
        {
            get { return string.Join(", ", _roles); }
        }

        /// <summary>
        /// Obtient le mot de passe de l'utilisateur courant
        /// </summary>
        public SecureString UserPassword { get { return _password; } }

        /// <summary>
        /// Validate the user credentials
        /// </summary>
        public unsafe void ValidateCredentials(string login, string password)
        {
            if (string.IsNullOrWhiteSpace(login) || string.IsNullOrWhiteSpace(password)) return;
            try
            {
                // TODO : Call to Authentication web api


                CreateIdentity(login, new string[] { "Administrator" });
                
                var chars = password.ToCharArray();
                fixed (char* pChars = chars)
                {
                    _password = new SecureString(pChars,chars.Length);
                    _password.MakeReadOnly();
                }
            }
            catch (Exception)
            {
                throw;
            }
            
        }

        private void CreateIdentity(string username, string[] roles)
        {
            _roles = roles;
            _currentIdentity = new GenericPrincipal(new GenericIdentity(username), roles);
            this.RaisePropertyChanged(() => CurrentIdentity);
            this.RaisePropertyChanged(() => UserName);
            this.RaisePropertyChanged(() => UserRoles);
            this.RaisePropertyChanged(() => IsAuthenticated);
        }
    }
}